package myjava.m_dynamicCompile;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @Auther: cty
 * @Date: 2020/4/13 17:32
 * @Description:
 * @version: 1.0
 */
public class DynamicCompile {
    // 获取当前工程路径
    static String projectPath = System.getProperty("user.dir");
    // 指定文件输出路径
    static String path = projectPath+"\\DynamicCompile\\myjava.p_classLoader.mycode\\";

    // 方式一：Runtime
    public static void runtimeExecute(String fileName){
        System.out.println("Runtime方法运行字节码文件输出结果为：");
        try {
            Runtime run = Runtime.getRuntime();
            Process process = run.exec("java -cp "+path+" "+fileName);

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String info = "";
            while ((info=reader.readLine())!=null){
                System.out.println(info);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //方式二：反射 类加载器
    public static void reflectExecute(String fileName){
        System.out.println("反射方法运行字节码文件输出结果为：");
        try {
            URL[] urls = new URL[]{new URL("file:/"+path)};
            URLClassLoader loader = new URLClassLoader(urls);
            // 加载类对象
            Class c = loader.loadClass(fileName);
            // 获取main方法对象
            Method m = c.getMethod("main", String[].class);
            // 执行main方法
            m.invoke(null, (Object)new String[]{});
            //可变参数是JDK5.0增加的。
            //m.invoke(null, new String[]{"aa", "bb"});会编译成:m.invoke(null,"aa","bb"),就发生了参数个数不匹配的问题。
            //因此，必须要加上(Object)转型，避免这个问题。

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("加载类失败");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            System.out.println("获取方法对象失败");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            System.out.println("执行方法失败");
        }
    }

    public static void main(String[] args){

        /* 动态编译 */
        // 获取Java编译器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 载入Java源代码并编译（产生字节码文件）

        int result = compiler.run(null,null,null, path+"myjava.p_classLoader.Hi.java");
        // 输出编译结果
        System.out.println(result==0?"编译成功":"编译失败");

        /* 运行字节码文件 */
        runtimeExecute("myjava.p_classLoader.Hi");
        reflectExecute("myjava.p_classLoader.Hi");
    }
}

/* res: 2020年4月13日
待编译Java源代码所在路径为：E:\JAVAXX\IdeaProjects\JavaPro\DynamicCompile\myjava.p_classLoader.mycode\
编译成功
Runtime方法运行字节码文件输出结果为：
Hello World!
反射方法运行字节码文件输出结果为：
Hello World!
*/
